#include <QStringBuilder>
#include <QDir>
#include <QColor>
#include <QDebug>
#include "ProjectRunner.h"
#include "Include/IConsole.h"
#include "Include/Project.h"
#include "Settings/Settings.h"

namespace Plugins
{
    ProjectRunner::ProjectRunner(IConsole* console, Project* project, QObject *parent) :
        QObject(parent),
        _console(console),
        _project(project)
    {
        _console->setRoot(_project->path());
    }

    ProjectRunner::~ProjectRunner()
    {
        qDebug() << "remove project runner";
    }

    void ProjectRunner::start()
    {
        _console->addLine("Run project " % _project->name(), "bold");
        _proc = new QProcess(this);
        QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
        env.insert("LANG", "en_US.UTF-8");
        _proc->setProcessEnvironment(env);
        connect(_proc, SIGNAL(readyRead()), SLOT(onReadyRead()));
        connect(_proc, SIGNAL(readyReadStandardError()), SLOT(onReadyReadError()));
        connect(_proc, SIGNAL(finished(int)), SLOT(onRunFinished(int)));
        connect(_proc, SIGNAL(error(QProcess::ProcessError)), SLOT(onRunError(QProcess::ProcessError)));
        _proc->setWorkingDirectory(_project->path());
        _proc->start(Project::currentInstance()->python(), QStringList() << "-u" << _project->mainScript());
        _console->clearConsole();
    }

    void ProjectRunner::onReadyRead()
    {
        _proc->setReadChannel(QProcess::StandardOutput);
        QByteArray text;
        while(!(text = _proc->readLine()).isEmpty())
            _console->addLine(text);
    }

    void ProjectRunner::onReadyReadError()
    {
        _proc->setReadChannel(QProcess::StandardError);
        QByteArray text;
        while(!(text = _proc->readLine()).isEmpty())
            _console->addLine(text, "error");
    }

    void ProjectRunner::onRunFinished(int status)
    {
        _console->addLine(tr("Project finished with status %1").arg(status), "bold");
        _proc->deleteLater();
        emit finished();
    }

    void ProjectRunner::onRunError(QProcess::ProcessError err)
    {
        switch(err){
        case QProcess::FailedToStart:
            _console->addLine(tr("The process failed to start. Either the invoked program is missing, or you may have insufficient permissions to invoke the program."), "error bold");
            break;
        case QProcess::Crashed:
            _console->addLine(tr("The process crashed some time after starting successfully."), "error bold");
            break;
        case QProcess::Timedout:
            _console->addLine(tr("The last waitFor...() function timed out."), "error bold");
            break;
        case QProcess::WriteError:
            _console->addLine(tr("An error occurred when attempting to write to the process. For example, the process may not be running, or it may have closed its input channel."), "error bold");
            break;
        case QProcess::ReadError:
            _console->addLine(tr("An error occurred when attempting to read from the process. For example, the process may not be running."), "error bold");
            break;
        default:
            _console->addLine(tr("An error occurred when attempting to read from the process. For example, the process may not be running."), "error bold");
            break;
        }
    }
}
